# 修改为只生成一个图片的版本
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sqlalchemy import create_engine
import pymysql
import warnings
warnings.filterwarnings('ignore')

# 数据库连接配置
db_config = {
    'host': 'localhost',
    'user': 'root',
    'password': '1234',
    'database': 'tushare1',
    'port': 3306,
    'charset': 'utf8mb4'
}

try:
    # 创建数据库连接
    engine = create_engine(
        f"mysql+pymysql://{db_config['user']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}?charset={db_config['charset']}"
    )
    conn = pymysql.connect(**db_config)
    
    print("数据库连接成功！")
    
    # 获取华夏银行日线数据（只获取必要列）
    query = """
        SELECT d.trade_date, d.closes, d.vol, i.closes as i_closes
        FROM date_1 d
        LEFT JOIN index_daily i ON d.trade_date = i.trade_date AND i.ts_code='000001.SH'
        WHERE d.trade_date BETWEEN '2023-01-01' AND '2023-12-31' AND d.ts_code='600015.SH'
        ORDER BY d.trade_date
    """
    
    df = pd.read_sql_query(query, conn)
    
    if df.empty:
        raise ValueError("查询返回空数据集")
    
    print(f"成功获取 {len(df)} 条数据")
    print("数据前5行:\n", df.head())
    
    # 数据预处理（更安全的方式）
    def preprocess_data(df):
        # 转换日期格式
        df['trade_date'] = pd.to_datetime(df['trade_date'])
        
        # 确保数值列是float类型
        num_cols = ['closes', 'vol', 'i_closes']
        for col in num_cols:
            if col in df.columns:
                df[col] = pd.to_numeric(df[col], errors='coerce')
        
        # 计算收益率（只计算华夏银行数据，不依赖上证指数数据）
        df['return'] = df['closes'].pct_change()
        
        # 计算移动平均线
        df['ma5'] = df['closes'].rolling(window=5).mean()
        df['ma20'] = df['closes'].rolling(window=20).mean()
        
        # 只删除closes为NA的行（保留其他列可能有NA的数据）
        df = df[df['closes'].notna()]
        
        return df
    
    df_processed = preprocess_data(df.copy())
    print("\n预处理后的数据前5行:\n", df_processed.head())
    print("\n数据统计描述:\n", df_processed.describe())
    
    # 检查是否有足够数据绘图
    if len(df_processed) == 0:
        raise ValueError("预处理后数据为空，无法生成图表")
    
    # 创建单一可视化图表
    plt.figure(figsize=(14, 8))
    plt.title('华夏银行(600015.SH)2023年股票综合分析', fontsize=16, pad=20)
    
    # 主图：价格走势和交易量
    ax1 = plt.gca()
    
    # 绘制收盘价
    ax1.plot(df_processed['trade_date'], df_processed['closes'], 
             label='收盘价', color='blue', linewidth=2)
    
    # 只有当有足够数据时才绘制均线
    if len(df_processed) >= 5:
        ax1.plot(df_processed['trade_date'], df_processed['ma5'], 
                 label='5日均线', color='orange', linestyle='--', alpha=0.8)
    if len(df_processed) >= 20:
        ax1.plot(df_processed['trade_date'], df_processed['ma20'], 
                 label='20日均线', color='green', linestyle='--', alpha=0.8)
    
    ax1.set_ylabel('价格', fontsize=12)
    ax1.legend(loc='upper left')
    ax1.grid(True)
    
    # 添加交易量柱状图（使用次坐标轴）
    ax2 = ax1.twinx()
    if df_processed['vol'].notna().sum() > 0:
        ax2.bar(df_processed['trade_date'], df_processed['vol'], 
                color='gray', alpha=0.3, width=0.8, label='交易量')
        ax2.set_ylabel('交易量', fontsize=12)
        ax2.legend(loc='upper right')
    
    # 在图表下方添加收益率分布箱线图
    plt.figure(1).subplots_adjust(bottom=0.3)
    ax3 = plt.axes([0.1, 0.1, 0.8, 0.15])
    
    if df_processed['return'].notna().sum() > 0:
        sns.boxplot(x=df_processed['return'].dropna(), ax=ax3, color='skyblue', width=0.3)
        ax3.set_title('日收益率分布箱线图', fontsize=10)
        ax3.set_xlabel('日收益率', fontsize=10)
        ax3.grid(True)
    else:
        ax3.text(0.5, 0.5, '无有效收益率数据', 
                ha='center', va='center', fontsize=10)
    
    plt.tight_layout()
    
    # 保存图片
    plt.savefig('stock_analysis_single.png', dpi=300, bbox_inches='tight')
    print("\n可视化图表已保存为 stock_analysis_single.png")
    plt.show()

except Exception as e:
    print(f"出错: {e}")
finally:
    if 'conn' in locals():
        conn.close()
    if 'engine' in locals():
        engine.dispose()

print("\n分析完成！")